var feedgraph = new Object();

var base = "http://api.feedgraph.com/";

feedgraph.setCookie = function (name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

feedgraph.getCookie = function (name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

feedgraph.clearCookie = function (name) {
	feedgraph.setCookie(name,"",-1);
}

feedgraph.uuid = function () {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
	    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
   	 return v.toString(16);
	});
}

feedgraph.retrieve = function (uri, callback) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("GET", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				callback(JSON.parse(req.responseText));
			} else {

				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

feedgraph.render = function (uri, templ, id, mode) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);

	var req = new XMLHttpRequest();
	req.open("GET", base + uri + ".html?t=" + escape(templ), true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				var container = document.getElementById(id);
			        var dummy = document.createElement("div");
				dummy.innerHTML = req.responseText;

				if (mode == "append") {
					for (var i = 0; i < dummy.childNodes.length; i++) {
						container.appendChild(dummy.childNodes[i]);
					}
				} else if (mode == "prepend") {
					for (var i = 0; i < dummy.childNodes.length; i++) {
						container.insertBefore(dummy.childNodes[i], container.firstChild);
					}
				} else {
					while (container.firstChild) {
						container.removeChild(container.firstChild);
					}
					for (var i = 0; i < dummy.childNodes.length; i++) {
						container.appendChild(dummy.childNodes[i]);
					}
				}

			} else {

				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

feedgraph.relations = function (uri, callback) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("GET", base + uri + "?relations", true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				callback(JSON.parse(req.responseText));
			} else {

				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

feedgraph.edges = function (uri, rel, callback) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("GET", base + uri + "?" + rel, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				callback(JSON.parse(req.responseText));
			} else {
				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

feedgraph.store = function (uri, obj, done) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("PUT", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				//alert("failed to send object to server");
				if (console) console.log(req);
			}
		}
	};

	req.send(JSON.stringify(obj));

	return req;
}

feedgraph.attach = function (uri, text, done) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("PUT", base + uri + ".txt", true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				//alert("failed to send object to server");
				if (console) console.log(req);
			}
		}
	};

	req.send(text);

	return req;
}


var postobj = function (uri, obj, done) {

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("POST", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				alert("failed to send object to server");
			}
		}
	};

	req.send();

	return req;
}

feedgraph.unlink = function (src, rel, sink, done) {

	var uri = src + "?" + escape(rel) + "&" + escape(sink);

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("DELETE", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

feedgraph.link = function (src, rel, sink, done) {

	var uri = src + "?" + escape(rel) + "&" + escape(sink);

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("PUT", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;

}

feedgraph.publish = function (node, msg) {

	var uri = node;
	var obj = msg;

	var uri = node;
	if (uri.charAt(0) == "/") uri = uri.substr(1);

	var req = new XMLHttpRequest();
	req.open("POST", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
			} else {
				if (console) console.log(req);
			}
		}
	};

	req.send(JSON.stringify(obj));

	return req;

}

feedgraph.subscribe = function (node, onMessage) {

	if (node.charAt(0) == "/") node = node.substr(1);

	var subscriber = "/s/" + feedgraph.uuid();

	feedgraph.link(node, "/subscribers", subscriber);

	feedgraph.listen(subscriber, onMessage);

	var obj = {};

	obj.unsubscribe = function() {
		feedgraph.unlink(node, "/subscribers", subscriber);
	}

	return obj;
}

feedgraph.listen = function (node, onMessage) {

	var uri = node;

	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("GET", base + uri + ".mailbox", true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				var arr = JSON.parse(req.responseText);
				for (var i = 0; i < arr.length; i++) {
					onMessage(arr[i]);
				}
				feedgraph.listen(node, onMessage);
			} else {
				if (console) console.log(req);
			}
		}
	};

	req.send();
}

feedgraph.delete = function (node, done) {

	var uri = node;
	if (uri.charAt(0) == "/") uri = uri.substr(1);
	
	var req = new XMLHttpRequest();
	req.open("DELETE", base + uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (done) done();
			} else {
				//alert("failed to send object to server");
				if (console) console.log(req);
			}
		}
	};

	req.send();

	return req;
}

/* stores obj at a new node and returns the new node's path */
feedgraph.newNode = function (obj, done) {

	var path = "/" + feedgraph.uuid();

	feedgraph.store(path, obj, done);

	return path;
}

/* stores obj at a new node and sends a msg referencing the node.
 * returns path to new node  */
feedgraph.sendNode = function (node, obj, done) {

	var path = feedgraph.newNode(obj);
	feedgraph.send(node, {"Node":path}, done);
	return path;
}

/* store obj at a new node and publish it to `node`.
 * returns path to new node */
feedgraph.publishNode = function (node, obj, done) {

	var path = feedgraph.newNode(obj);
	feedgraph.publish(node, {"Node":path}, done);
	return path;
}

feedgraph.subscribeNodes = function (path, onNode) {

	feedgraph.subscribe(path, function (msg) {

		if (msg && msg.Node) {
			feedgraph.retrieve(msg.Node, onNode);
		} else {
			if (console) console.log("msg not a NodeMessage");
		}

		});
}

feedgraph.subscribeRenderedNodes = function (path, templ, id, mode) {

	feedgraph.subscribe(path, function (msg) {

		if (msg && msg.Node) {
			feedgraph.render(msg.Node, templ, id, mode);
		} else {
			if (console) console.log("msg not a NodeMessage");
		}

		});
}
